﻿-- Author      : Kurapica

--[[
	In-Game Addon System
	Studio
	Core Part
--]]
do	
    local L = IGAS:NewLocal("IGAS.Studio")
    local pairs = pairs
    local ipairs = ipairs
    local type = type
    local error = error
	local twipe = table.wipe
	local _Widget = IGAS.GUI.Widget
	local _StudioWidget = IGAS.Studio.Widget
	local _BaseFunc = IGAS.GUI.Base.Func
	
    local GetWrapper = IGAS.GUI.GetWrapper
	local S_UIParent = IGAS.Studio.UIParent
	local WidgetList = S_UIParent.IGAS_STUDIO_WidgetList
	local PropertyList = S_UIParent.IGAS_STUDIO_PropertyList
	local ControlPanel = S_UIParent.IGAS_STUDIO_ControlPanel
	
	local _InDesignFrameList = {}
	local _InDesignContainerList = {}
	
	-- Hook CreateFrame
	local _Selector = IGAS:NewFrame(_StudioWidget.Selector, "IGAS_STUDIO_Selector", S_UIParent, WidgetList)
	local _Marker = IGAS:NewFrame(_StudioWidget.Marker, "IGAS_STUDIO_Marker", S_UIParent, WidgetList)
			
	-- Hook CreateFrame
	local _OriCreateFrame = _BaseFunc.CreateFrame
	local _NestLevel = 0
	
	_BaseFunc.CreateFrame = function(frameType,frameName,parentFrame,...)	
		local frame, useShadow
		
		parentFrame = parentFrame or UIParent
		parentFrame = _BaseFunc.GetWrapper(parentFrame)
		
		useShadow = false
		
		-- Pre CreateFrame
		if S_UIParent.StartDesign then
			if parentFrame == GetWrapper(UIParent) then
				parentFrame = S_UIParent
			end
		end
		
		---- Check FrameType
		if not frameType then
			error("There must be a frame's type be set.", 2)
		elseif type(frameType) == "string" then
			if _Widget[frameType] then
				frameType = _Widget[frameType]
			else
				error("This frameType ["..frameType.."] is not exist.", 2)
			end
		elseif type(frameType) == "table" then
            if not frameType["FuncProxy"] then
				error("This frameType is invalid.", 2)
            end
		else
			error("This frameType is invalid.", 2)
		end
		
		if not frameType.New then
            error("This frameType ["..frameType.Name.."] is abstracted.", 2)
		end
		
		---- Check Parent
		if not parentFrame["AddChild"] then
			error("Can't add child to the object ["..(parentFrame.Name or tostring(parentFrame)).."].", 2)
		end
		
		---- Check FrameName
        if frameName and type(frameName) ~= "string" then
            error("name must be string.", 2)
        end
		
        if frameName and frameName ~= "" then
            -- Check the parent's childs
            if parentFrame["GetChild"] and parentFrame:GetChild(frameName) then
            	if parentFrame:GetChild(frameName)["GetObjectType"] and parentFrame:GetChild(frameName):GetObjectType() == frameType then
            		return parentFrame:GetChild(frameName)
            	else
            		error("this name ["..frameName.."] is used", 2)
            	end
            end
        end
		
		_NestLevel = _NestLevel + 1
		
		-- Check if need use ShadowFrame
		if S_UIParent.StartDesign and _NestLevel == 1 and (not frameType["FuncProxy"]["EnableMouse"]) then
			useShadow = true
		end
		
		-- CreateFrame
		if useShadow then
			frame = _OriCreateFrame(_StudioWidget.ShadowFrame, frameName, parentFrame, frameType, ...)
		else
			frame = _OriCreateFrame(frameType, frameName, parentFrame, ...)
		end
		
		-- Post CreateFrame
		if frame and S_UIParent.StartDesign then
			-- Mark the first level frame
			if _NestLevel == 1 then
				-- Mark the Container
				if frame.Container and frame.Container.IsIGASWidget then
					_Selector:HookFrame(frame.Container)
				end			
				
				-- Mark InDesignMode
				frame.__InDesignMode = true
				
				_Selector:HookFrame(frame)
				_Marker:HookFrame(frame)
				
				PropertyList:AddFrame(frame)
				_InDesignFrameList[frame] = true
			end
		end
		
		_NestLevel = _NestLevel - 1
		
		return frame
	end
	
	-- Other entrance
	IGAS.GUI.CreateFrame = _BaseFunc.CreateFrame
	IGAS:RegisterFunction("NewFrame", function(self, ...)
		return _BaseFunc.CreateFrame(...)
	end)
	
    local CreateFrame = IGAS.GUI.CreateFrame
	
	-- Selector
	_Selector:HookFrame(S_UIParent)
		
	-- Scripts
	S_UIParent.StartDesign = false
	
	-- Selector's script
	function _Selector:OnAreaSelected(stF, stX, stY, endX, endY)

		S_UIParent.StartDesign = true
		
		-- Check if stF is a ShadowFrame, use it's parent instead of itself
		if stF:IsObjectType(_StudioWidget.ShadowFrame) then
			stF = stF.Parent
		end
		
		local frame = CreateFrame(WidgetList.SelectedWidget, nil, stF)
		
		S_UIParent.StartDesign = false
		
		-- Use marker not frame self to set points
		frame:ClearAllPoints()
		frame.Width = endX - stX
		frame.Height = stY - endY
		frame:SetPoint("TOPLEFT", stF, "TOPLEFT", stX - stF:GetLeft(), stY - stF:GetTop())
		
		WidgetList:DisSelected()
	end
	
	-- Marker's script
	function _Marker:OnSelected(frame)
		if frame and frame:IsObjectType(_StudioWidget.ShadowFrame) then
			PropertyList.SelectedFrame = frame.TrueFrame
		else
			PropertyList.SelectedFrame = frame
		end
	end
		
	-- OnWidgetSelected
	function WidgetList:OnWidgetSelected()
		_Marker.InMarkMode = (not self.SelectedWidget and true) or false
	end
	
	-- DisSelect Item
	function S_UIParent:OnMouseDown()
		_Marker.MarkedFrame = nil
	end
	
	-- Dispose Item
	function PropertyList:OnFrameDispose(frame)
		_Marker.MarkedFrame = nil
		_InDesignFrameList[frame] = nil
	end
	
	-- Special actions when property is set
	function PropertyList:OnPropertyChanged(obj, prop, value)
		-- Action for property : Name
		if prop == "Name" then
			PropertyList.SelectedFrame = nil
			PropertyList:RemoveFrame(obj)
			PropertyList:AddFrame(obj)
			PropertyList.SelectedFrame = obj
		end
	end
	
	-- Export & Import Code
	function S_UIParent:Export()
		
	end
	
	function S_UIParent:Import(code)
		
	end
	
	function S_UIParent:Clear()
		
	end
end